home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1997 #1 / Amiga Plus Extra 1997 #1.iso / programme / tools / leoutils / scrdump.c < prev    next >
C/C++ Source or Header  |  1996-11-25  |  11KB  |  418 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <libraries/asl.h>
  6. #include <libraries/iff.h>    /* The great IFF library    */
  7. #include <exec/exec.h>
  8. #include <graphics/displayinfo.h>
  9. #include <intuition/intuitionbase.h>
  10. #if defined __SASC
  11. #include <proto/intuition.h>
  12. #include <proto/asl.h>
  13. #include <proto/dos.h>
  14. #include <proto/graphics.h>
  15. #include <proto/exec.h>
  16. #else
  17. #include <clib/intuition_protos.h>
  18. #include <clib/asl_protos.h>
  19. #include <clib/dos_protos.h>
  20. #include <clib/graphics_protos.h>
  21. #include <clib/exec_protos.h>
  22. #endif
  23.  
  24. #define VERSION "1.1"
  25.  
  26. /***********************************************\
  27. *                                                *
  28. *    ILBM basic definitions                        *
  29. *                                                *
  30. \***********************************************/
  31.  
  32. /* ILBM compression techniques */
  33. #define cmpNone      0
  34. #define cmpByteRun1  1
  35.  
  36. /* ILBM masking techniques */
  37. #define    mskNone                    0
  38. #define    mskHasMask                1
  39. #define    mskHasTransparentColor    2
  40. #define    mskLasso                3
  41.  
  42. /***********************************************\
  43. *                                                *
  44. *    Needed for iff.library                        *
  45. *                                                *
  46. \***********************************************/
  47.  
  48. /* A macro */
  49. #define MAXPACKEDSIZE(s)    ((s)*2)
  50.  
  51. /* how many bytes to buffer in BODY chunk */
  52. #define BODYBUFSIZE            10000
  53.  
  54.  
  55. /***********************************************\
  56. *                                                *
  57. *    Constants and variables                        *
  58. *                                                *
  59. \***********************************************/
  60.  
  61. static char *Ver = "$VER:ScrDump " VERSION " " __AMIGADATE__ " ©1995-6 Leopold-Soft";
  62.  
  63. typedef enum SAVEMODE {
  64.     SM_WIN,
  65.     SM_SCR
  66. };
  67.  
  68. typedef enum ERRORCODE {
  69.     EC_NONE,
  70.     EC_NO_ACTIVE_WIN,
  71.     EC_OLD_OR_NO_IFF_LIBRARY,
  72.     EC_OLD_OS,
  73.     EC_CANT_SAVE
  74. };
  75.  
  76. #define SF_NOWINBORDERS    (1<<0)
  77. #define SF_SAFE            (1<<1)
  78.  
  79. static char *defaultFileName = "RAM:ScrDumpFile";
  80.  
  81. /***********************************************\
  82. *                                                *
  83. *    SaveScrWin saves a window or screen to the    *
  84. *    given file.                                    *
  85. *                                                *
  86. \***********************************************/
  87.  
  88. static int SaveScrWin(struct Screen *scr, struct Window *win, char *name, ULONG flags) {
  89.     extern struct IntuitionBase *IntuitionBase;
  90.     extern struct ExecBase *SysBase;
  91.     struct Library *IFFBase;
  92.     IFFL_HANDLE iffH;
  93.     BOOL success = FALSE;
  94.     UBYTE *bodyBuf = NULL;
  95.     struct IFFL_BMHD bmhd;
  96.     UBYTE *oneLine = NULL;
  97.     enum SAVEMODE mode = scr ? SM_SCR : SM_WIN;
  98.     BOOL OS3 = SysBase->LibNode.lib_Version >= 39;
  99.     struct RastPort *srcRPort;
  100.     struct DisplayInfo myDisplayInfo;
  101.     UBYTE *colors = NULL;
  102.     BOOL quickSave = (!OS3 || (mode == SM_SCR &&
  103.                         GetBitMapAttr(scr->RastPort.BitMap, BMA_FLAGS)
  104.                             & BMF_STANDARD));
  105.     LONG depth, xStart=0, yStart=0, width, height;
  106.     int i;
  107.     ULONG modeID, iffrowbytes;
  108.     struct RastPort stdLineRPort1, stdLineRPort2, scrLineRPort;
  109.     struct BitMap *stdLineBMap1=NULL, *stdLineBMap2=NULL, *scrLineBMap=NULL;
  110.     char vStr[80];
  111.     time_t tt;
  112.     struct tm *t;
  113.  
  114.     if (!OS3 && mode == SM_WIN)
  115.         return EC_OLD_OS;
  116.  
  117.     if (!(IFFBase = OpenLibrary(IFFNAME, 21L)))
  118.         return EC_OLD_OR_NO_IFF_LIBRARY;
  119.  
  120.     if (name == NULL || name[0] == '\0')
  121.         name = defaultFileName;
  122.  
  123.     if (mode == SM_WIN) {
  124.         scr = win->WScreen;
  125.         srcRPort = win->RPort;
  126.     } else {
  127.         srcRPort = &scr->RastPort;
  128.     }
  129.  
  130.     modeID = GetVPModeID(&scr->ViewPort);
  131.  
  132.     if (OS3) {
  133.         depth = GetBitMapAttr(srcRPort->BitMap, BMA_DEPTH);
  134.     } else {
  135.         depth = srcRPort->BitMap->Depth;
  136.     }
  137.  
  138.     if (mode == SM_WIN) {
  139.         if (flags && SF_NOWINBORDERS) {
  140.             xStart = win->BorderLeft;
  141.             yStart = win->BorderTop;
  142.             width  = win->Width  - xStart - win->BorderRight;
  143.             height = win->Height - yStart - win->BorderBottom;
  144.         } else {
  145.             width = win->Width;
  146.             height = win->Height;
  147.         }
  148.     } else {
  149.         width  = scr->Width;
  150.         height = scr->Height;
  151.     }
  152.  
  153.     iffrowbytes = ((width + 15L) & ~15L) >> 3;
  154.  
  155.     GetDisplayInfoData(NULL, (UBYTE *) &myDisplayInfo, sizeof(struct DisplayInfo),
  156.             DTAG_DISP, modeID);
  157.  
  158.     if (!(colors = malloc((1<<depth) * 3)) ||
  159.         !(bodyBuf = malloc(BODYBUFSIZE)))
  160.         goto error;
  161.  
  162.     if (!quickSave) {
  163.         if (!(stdLineBMap1 = AllocBitMap(width+16, 1, depth, BMF_MINPLANES, NULL)) ||
  164.             !(stdLineBMap2 = AllocBitMap(width+16, 1, depth, BMF_MINPLANES, NULL)) ||
  165.             !(scrLineBMap  = AllocBitMap(scr->Width, 1, depth, BMF_MINPLANES, srcRPort->BitMap)) ||
  166.             !(oneLine = malloc((iffrowbytes<<3) + 16)))
  167.             goto error;
  168.  
  169.         InitRastPort(&stdLineRPort1);
  170.         stdLineRPort1.BitMap = stdLineBMap1;
  171.         InitRastPort(&stdLineRPort2);
  172.         stdLineRPort2.BitMap = stdLineBMap2;
  173.         scrLineRPort = *srcRPort;
  174.         scrLineRPort.Layer = NULL;
  175.         scrLineRPort.BitMap = scrLineBMap;
  176.     }
  177.  
  178.     iffH = IFFL_OpenIFF(name, IFFL_MODE_WRITE);
  179.  
  180.     if (iffH) {
  181.         /*
  182.             Let's write the BMHD chunk
  183.         */
  184.  
  185.         bmhd.w                    = width;
  186.         bmhd.h                    = height;
  187.         bmhd.x                    = xStart;
  188.         bmhd.y                    = yStart;
  189.         bmhd.nPlanes            = depth;
  190.         bmhd.masking            = mskNone;
  191.         bmhd.compression        = cmpByteRun1;
  192.         bmhd.pad1                = 0;
  193.         bmhd.transparentColor    = 0;
  194.         bmhd.xAspect            = myDisplayInfo.Resolution.y;
  195.         bmhd.yAspect            = myDisplayInfo.Resolution.x;
  196.         bmhd.pageWidth            = bmhd.w;
  197.         bmhd.pageHeight            = bmhd.h;
  198.         success = IFFL_PushChunk(iffH, ID_ILBM, ID_BMHD);
  199.         if (success) success = IFFL_WriteChunkBytes(iffH, &bmhd, sizeof(bmhd));
  200.         if (success) success = IFFL_PopChunk(iffH);
  201.  
  202.  
  203.         /*
  204.             Let's write the CMAP chunk
  205.         */
  206.         if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_CMAP);
  207.         for (i=0; i<(1<<depth); i++) {
  208.             ULONG tmpCol[3];
  209.  
  210.             if (OS3) {
  211.                 GetRGB32(scr->ViewPort.ColorMap, (ULONG)i, 1, tmpCol);
  212.                 colors[i*3+0] = tmpCol[0] >> 24;
  213.                 colors[i*3+1] = tmpCol[1] >> 24;
  214.                 colors[i*3+2] = tmpCol[2] >> 24;
  215.             } else {
  216.                 tmpCol[0] = GetRGB4(scr->ViewPort.ColorMap, (ULONG)i);
  217.                 colors[i*3+0] = ((tmpCol[0]            ) >> 8) * 0x11;
  218.                 colors[i*3+1] = ((tmpCol[0] & 0x0F0 ) >> 4) * 0x11;
  219.                 colors[i*3+2] = ((tmpCol[0] & 0x00F )      ) * 0x11;
  220.             }
  221.         }
  222.         if (success) success = IFFL_WriteChunkBytes(iffH, colors, (LONG)(1<<depth)*3);
  223.         if (success) success = IFFL_PopChunk(iffH);
  224.  
  225.  
  226.         /*
  227.             Let's write a CAMG chunk
  228.         */
  229.         if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_CAMG);
  230.         if (success) success = IFFL_WriteChunkBytes(iffH, &modeID, sizeof(modeID));
  231.         if (success) success = IFFL_PopChunk(iffH);
  232.  
  233.         /*
  234.             Let's write an ANNO chunk
  235.         */
  236.         time(&tt);
  237.         t = localtime(&tt);
  238.         strcpy(vStr, "$VER: Written by ScrDump " VERSION " (");
  239.         i = strlen(vStr);
  240.         t->tm_mon++;
  241.         vStr[i++] = '0' + t->tm_mday/10;
  242.         vStr[i++] = '0' + t->tm_mday%10;
  243.         vStr[i++] = '.';
  244.         vStr[i++] = '0' + t->tm_mon/10;
  245.         vStr[i++] = '0' + t->tm_mon%10;
  246.         vStr[i++] = '.';
  247.         vStr[i++] = '0' + (t->tm_year%100)/10;
  248.         vStr[i++] = '0' + t->tm_year%10;
  249.         strcpy(vStr + i, ") ©1995-6 Leopold-Soft");
  250.  
  251. /*        sprintf(vStr, "%02d.%02d.%02d) ©1995-6 Leopold-Soft",
  252.             t->tm_mday, t->tm_mon, t->tm_year % 100);
  253. */
  254.         if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_ANNO);
  255.         if (success) success = IFFL_WriteChunkBytes(iffH, vStr, strlen(vStr)+1);
  256.         if (success) success = IFFL_PopChunk(iffH);
  257.  
  258.         /*
  259.             Let's write a BODY chunk
  260.         */
  261.         if (success) {
  262.             int row, iplane, bodysize=0;
  263.             int rowOffset = -srcRPort->BitMap->BytesPerRow;
  264.  
  265.             success = IFFL_PushChunk(iffH, ID_ILBM, ID_BODY);
  266.  
  267.             for (row=0; row < bmhd.h; ++row) {
  268.                 if (!quickSave) {
  269.                     int i;
  270.                     ReadPixelLine8(          srcRPort, xStart, row+yStart, width, oneLine, &scrLineRPort);
  271.                     for (i=0; i<16; i++)
  272.                         oneLine[width+i] = 0;
  273.                     WritePixelLine8(&stdLineRPort1,      0,       0, width+16, oneLine, &stdLineRPort2);
  274.                 } else {
  275.                     rowOffset += srcRPort->BitMap->BytesPerRow;
  276.                 }
  277.                 for (iplane=0; iplane < depth; ++iplane) {
  278.                     int comprsize;
  279.  
  280.                     /* Flush buffer if full */
  281.                     if (bodysize > (BODYBUFSIZE-MAXPACKEDSIZE(iffrowbytes))) {
  282.                         if (success) {
  283.                             success = IFFL_WriteChunkBytes(iffH, bodyBuf, bodysize);
  284.                             bodysize = 0;
  285.                         }
  286.                     }
  287.  
  288.                     /* Compress one row    */
  289.                     if (success) {
  290.                         if (!quickSave) {
  291.                             success = comprsize = IFFL_CompressBlock(
  292.                                     stdLineRPort1.BitMap->Planes[iplane],
  293.                                     bodyBuf+bodysize, iffrowbytes, IFFL_COMPR_BYTERUN1);
  294.                         } else {
  295.                             success = comprsize = IFFL_CompressBlock(
  296.                                     srcRPort->BitMap->Planes[iplane] + rowOffset,
  297.                                     bodyBuf+bodysize, iffrowbytes, IFFL_COMPR_BYTERUN1);
  298.                         }
  299.                         bodysize += comprsize;
  300.                     }
  301.                 }
  302.             }
  303.  
  304.             /* Flush the rest of body */
  305.             if (bodysize && success)
  306.                 success = IFFL_WriteChunkBytes(iffH, bodyBuf, bodysize);
  307.  
  308.             if (success) success = IFFL_PopChunk(iffH);
  309.         }
  310.         IFFL_CloseIFF(iffH);
  311.     }
  312.  
  313. error:
  314.     if (oneLine) free(oneLine);
  315.     if (scrLineBMap) FreeBitMap(scrLineBMap);
  316.     if (stdLineBMap2) FreeBitMap(stdLineBMap2);
  317.     if (stdLineBMap1) FreeBitMap(stdLineBMap1);
  318.     if (bodyBuf) free(bodyBuf);
  319.     if (colors) free(colors);
  320.  
  321.     CloseLibrary(IFFBase);
  322.  
  323.     return success ? EC_NONE : EC_CANT_SAVE;
  324. }
  325.  
  326.  
  327.  
  328. static int SaveScreen(struct Screen *scr, char *name, ULONG flags) {
  329.     return SaveScrWin(scr, NULL, name, flags);
  330. }
  331.  
  332.  
  333.  
  334. static int SaveWindow(struct Window *win, char *name, ULONG flags) {
  335.     return SaveScrWin(NULL, win, name, flags);
  336. }
  337.  
  338.  
  339.  
  340. /***********************************************\
  341. *                                                *
  342. *    The main program                            *
  343. *                                                *
  344. \***********************************************/
  345.  
  346. int main(int argc, char **argv) {
  347.     int errorcode = EXIT_SUCCESS;
  348.     int i;
  349.     enum SAVEMODE savemode = SM_SCR;
  350.     ULONG flags = 0;
  351.     char *fileName = defaultFileName;
  352.  
  353.     for (i = 1; i < argc; i++) {
  354.         if (!strcmp(argv[i], "-w")) {
  355.             savemode = SM_WIN;
  356.         } else if (!strcmp(argv[i], "-s")) {
  357.             savemode = SM_SCR;
  358.         } else if (!strcmp(argv[i], "-b")) {
  359.             flags |= SF_NOWINBORDERS;
  360.         } else if (!strcmp(argv[i], "-B")) {
  361.             flags &= ~SF_NOWINBORDERS;
  362.         } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "?")) {
  363.             Printf("\nScreen Dump v" VERSION " ©1995-6 Leopold-Soft\n"
  364.                     "Usage: %s [-w] [-s] [-b] [-B] [-h|?] [filnam]\n"
  365.                     "-w\tSave active window (requires OS3)\n"
  366.                     "-s\tSave uppermost screen (default)\n"
  367.                     "-b\tDon't save window borders\n"
  368.                     "-B\tSave window borders (default)\n"
  369.                     "-h|?\tShow this help\n"
  370.                     "filnam\tSpecify file name to save to (default: %s)\n\n"
  371.                     , argv[0], defaultFileName);
  372.             return EXIT_SUCCESS;
  373.         } else {
  374.             fileName = argv[i];
  375.         }
  376.     }
  377.  
  378.     Delay(500);
  379.  
  380.     switch(savemode) {
  381.         case SM_SCR:
  382.             errorcode = SaveScreen(IntuitionBase->FirstScreen, fileName, flags);
  383.             DisplayBeep(IntuitionBase->FirstScreen);
  384.             break;
  385.         case SM_WIN:
  386.             if (!IntuitionBase->ActiveWindow) {
  387.                 errorcode = EC_NO_ACTIVE_WIN;
  388.             } else {
  389.                 errorcode = SaveWindow(IntuitionBase->ActiveWindow, fileName, flags);
  390.                 DisplayBeep(IntuitionBase->ActiveWindow->WScreen);
  391.             }
  392.             break;
  393.     }
  394.  
  395.     switch (errorcode) {
  396.         case EC_NONE:
  397.             Printf("%s: Saved to \"%s\", ok!\n", argv[0], fileName);
  398.             break;
  399.         case EC_NO_ACTIVE_WIN:
  400.             Printf("%s: Error: no active window!\n", argv[0]);
  401.             errorcode = EXIT_FAILURE;
  402.             break;
  403.         case EC_OLD_OR_NO_IFF_LIBRARY:
  404.             Printf("%s: Error: iff.library v21 or newer required!\n", argv[0]);
  405.             errorcode = EXIT_FAILURE;
  406.             break;
  407.         case EC_OLD_OS:
  408.             Printf("%s: Error: Can't save windows under OS2.x!\n", argv[0]);
  409.             errorcode = EXIT_FAILURE;
  410.             break;
  411.         default:
  412.             Printf("%s: Error: can't save to \"%s\"!\n", argv[0], fileName);
  413.             errorcode = EXIT_FAILURE;
  414.             break;
  415.     }
  416.     return errorcode;
  417. }
  418.